﻿using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace Koala.Pro.Common
{
    public sealed class XmlConvertor
    {
        public static T XmlToObject<T>(string xml) where T : class
        {
            return XmlToObject(xml, typeof(T)) as T;
        }

        public static object XmlToObject(string xml, Type type)
        {
            if (xml == null)
            {
                throw new ArgumentNullException("xml");
            }
            if (null == type)
            {
                throw new ArgumentNullException("type");
            }
            object obj = null;
            XmlSerializer xmlSerializer = new XmlSerializer(type);
            XmlReader xmlReader = new XmlTextReader(new StringReader(xml));
            try
            {
                return xmlSerializer.Deserialize(xmlReader);
            }
            catch (InvalidOperationException innerException)
            {
                throw new InvalidOperationException("Can not convert xml to object", innerException);
            }
            finally
            {
                xmlReader.Close();
            }
        }

        public static string ObjectToXml(object obj, bool toBeIndented = false)
        {
            if (obj == null)
            {
                throw new ArgumentNullException("obj");
            }
            XmlSerializerNamespaces xmlSerializerNamespaces = new XmlSerializerNamespaces();
            xmlSerializerNamespaces.Add("", "");
            UTF8Encoding uTF8Encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
            XmlSerializer xmlSerializer = new XmlSerializer(obj.GetType());
            MemoryStream memoryStream = new MemoryStream();
            XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, uTF8Encoding);
            xmlTextWriter.Formatting = (toBeIndented ? Formatting.Indented : Formatting.None);
            try
            {
                xmlSerializer.Serialize(xmlTextWriter, obj, xmlSerializerNamespaces);
            }
            catch (InvalidOperationException)
            {
                throw new InvalidOperationException("Can not convert object to xml.");
            }
            finally
            {
                xmlTextWriter.Close();
            }
            return uTF8Encoding.GetString(memoryStream.ToArray());
        }

        public static string FormatXml(string xml)
        {
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(xml);
            StringBuilder stringBuilder = new StringBuilder();
            StringWriter w = new StringWriter(stringBuilder);
            XmlTextWriter xmlTextWriter = null;
            try
            {
                xmlTextWriter = new XmlTextWriter(w);
                xmlTextWriter.Formatting = Formatting.Indented;
                xmlTextWriter.Indentation = 1;
                xmlTextWriter.IndentChar = '\t';
                xmlDocument.WriteTo(xmlTextWriter);
            }
            finally
            {
                xmlTextWriter?.Close();
            }
            return stringBuilder.ToString();
        }
    }
}
